import {
  degreeInfo,
  KEYBOARD_KEY,
  MathTool,
  ParameterObjectType,
} from '@amcax/base';
import { Input, InputRef } from 'antd';
import { useEffect, useMemo, useRef, useState } from 'react';
import cx from 'classnames';
import useStateRef from 'react-usestateref';
import { DimColors } from '../type';
import { useFormatInput } from 'nextcae-base/src/common/components/command-form/useFormatInput';
import { CSS2DInputWrapper } from '@/components/Css2dReactObject/InputWrapper';
import { evaluate } from 'mathjs';
export type DimLabelProps = {
  type: ParameterObjectType;
  disabled: boolean;
  prefix: string;
  value: number;
  isEdit: boolean;
  allowActive: boolean;
  hovered: boolean;
  selected: boolean;
  onChange: (active: boolean, text?: number) => void;
  multiple: number;
};

const VIEW_PRECISION = 3;
const INPUT_PRECISION = 6;

export const DimLabel = ({
  type,
  value,
  prefix,
  isEdit,
  onChange,
  disabled,
  allowActive,
  hovered,
  selected,
  multiple,
}: DimLabelProps) => {
  const { parser, formatter, currentUnit } = useFormatInput({
    inputType: type,
    outerValue: value,
  });

  const getValueString = (val: string | number, includesUnit = true) => {
    const precision = isEdit ? INPUT_PRECISION : VIEW_PRECISION;
    return typeof val === 'number'
      ? formatter(value * multiple, includesUnit, precision)
      : formatter(value, includesUnit, precision);
  };

  const [innerValue, setInnerValue, innerValueRef] = useStateRef(
    getValueString(value),
  );

  useEffect(() => {
    setInnerValue(getValueString(value));
    if (isEdit) {
      window.requestAnimationFrame(() => {
        inputDomRef.current?.input?.focus({ preventScroll: true });
        inputDomRef.current?.input?.select();
      });
    }
  }, [value]);

  const [width, setWidth] = useState(null);

  const onSubmit = () => {
    onChange(
      false,
      (parser(calculate(innerValueRef.current)) as number) / multiple,
    );
    changeEventEmitted.current = true;
  };

  const changeEventEmitted = useRef(true);

  useEffect(() => {
    if (!isEdit) {
      if (changeEventEmitted.current) {
        return;
      }
      onSubmit();
    } else {
      setInnerValue(getValueString(value));
      setTimeout(() => {
        inputDomRef.current?.input?.focus({ preventScroll: true });
        inputDomRef.current?.input?.select();
      });

      changeEventEmitted.current = false;
    }
  }, [isEdit]);

  const onKeyUp = (e: KeyboardEvent) => {
    if (e.key === KEYBOARD_KEY.ESC) {
      changeEventEmitted.current = true;
      onChange(false);
      return;
    }
    if (e.key === KEYBOARD_KEY.ENTER) {
      onSubmit();
      return;
    }
  };

  useEffect(() => {
    if (isEdit) {
      document.addEventListener('keyup', onKeyUp, { capture: true });
    }

    return () => {
      document.removeEventListener('keyup', onKeyUp, { capture: true });
    };
  }, [isEdit]);

  const colors = useMemo(() => {
    if (disabled) {
      return DimColors.disable;
    }
    if (selected) {
      return DimColors.select;
    }

    if (hovered) {
      return DimColors.hover;
    }

    return DimColors.normal;
  }, [disabled, hovered, selected]);

  const baseDomRef = useRef<HTMLDivElement>();
  const inputDomRef = useRef<InputRef>();

  const onClickOut = (e: MouseEvent) => {
    if (
      inputDomRef.current != null &&
      !inputDomRef.current?.input?.contains(e.target as Node)
    ) {
      onSubmit();
    } else if (disabled) {
      onChange(false);
    }
  };

  useEffect(() => {
    document.addEventListener('click', onClickOut, { capture: true });

    return () => {
      document.removeEventListener('click', onClickOut, { capture: true });
    };
  }, []);

  return (
    <div
      className='relative'
      onPointerUp={(e) => {
        if (!disabled && e.button === 0 && allowActive && !isEdit) {
          e.stopPropagation();
          e.preventDefault();
        }
      }}>
      {
        <div
          ref={baseDomRef}
          className={cx(isEdit && 'hidden', 'cursor-pointer rounded-sm')}
          style={{
            backgroundColor: colors?.mask,
            color: colors?.text,
          }}
          onClick={(e) => {
            if (allowActive && !disabled && e.button === 0) {
              onChange(true);
              setWidth(baseDomRef.current.offsetWidth);
            }
          }}>
          {prefix +
            getValueString(value, false) +
            (currentUnit.name === degreeInfo.name ? '°' : '')}
        </div>
      }
      {isEdit && (
        <CSS2DInputWrapper>
          <div
            style={{
              width: (width ?? 100) + 20,
              height: 32,
            }}>
            <Input
              ref={inputDomRef}
              className='text-[15px] absolute'
              value={innerValue}
              onChange={(e) => {
                setInnerValue(e.target.value);
              }}
            />
          </div>
        </CSS2DInputWrapper>
      )}
    </div>
  );
};

function calculate(expression) {
  // 允许的字符集合
  const allowedChars = /^[0-9+\-*/().\s]*$/;
  // 检查表达式是否只包含允许的字符
  if (!allowedChars.test(expression)) {
    return expression;
  }
  try {
    // 计算表达式的值
    const result = evaluate(expression);
    return MathTool.fixNumber(result, 6).toString();
  } catch (error) {
    return expression;
  }
}
